#ifndef _NNSLITE_MTREE_H_
#define _NNSLITE_MTREE_H_

#include "nnsliteglobal.h"
#include "nnslitebufferedheapfile.h"
#include "nnsliteobjectcontainer.h"

/** nnsliteMTree */
struct nnsliteMTree;

typedef struct nnsliteMTreeNode
{
	struct nnsliteMTree* pTree;
	u32 nodeIndex;
	u32 parentIndex;
	u32 childCount;
	bool isLeaf;
	bool isUsed; /* This boolean value indicates this node whether being used */
	u32 depth;
	f64 radius;
	nnsliteObject object;
	u32 objContainerID;
	
	/* The child nodes's indexes. The actual maximum limitation of the number of child nodes is indicated by 
	 * the tree's "maxChildCont", which is less than the NNSLITE_MTREE_MAX_CHILD */
	u32 childIndexes[NNSLITE_MTREE_MAX_CHILD];
}nnsliteMTreeNode;

typedef struct nnsliteMTree
{
	/* The distance measure function */
	nnsliteDistFunc distfunc;
	
	/* The actual maximum count of child nodes of a node, which must be less than NNSLITE_MTREE_MAX_CHILD */
	u32 maxChildCount; 
	
	/* The maximum deepth of the tree, which is the deepest node's deepth. The root node's deepth is 0*/
	u32 maxDepth;

	/* The index of the root node in the nodes vector */
	u32 rootNodeIndex;

	/* The object container base. Each container maintains a node's objects */
	nnsliteObjectContainerBase* objContainerBase;

	/* The maximum number of the nodes */
	u32 maxNumNodes;
	
	/* all the nodes of the tree */
	nnsliteMTreeNode nodes[1];
}nnsliteMTree;

NNSLITE_RET nnsliteMTreeCreate(nnsliteMTree** tree, u32 maxnodes, u32 maxdepth, u32 childcount, 
		nnsliteObjectContainerBase* objContainerBase, nnsliteDistFunc func);
NNSLITE_RET nnsliteMTreeFree(nnsliteMTree* tree);
NNSLITE_RET nnsliteMTreeInsert(nnsliteMTree* tree, const nnsliteObject* object);
NNSLITE_RET nnsliteMTreeNNSearch(nnsliteMTree* tree, const nnsliteObject* object, u32 top, nnsliteObject* results);
NNSLITE_RET nnsliteMTreeWrite(nnsliteMTree* tree, nnsliteBufferedHeapFile* bhf);
NNSLITE_RET nnsliteMTreeRead(nnsliteMTree** tree, nnsliteBufferedHeapFile* bhf);
NNSLITE_RET nnsliteMTreePrint(nnsliteMTree* tree, FILE* fp);

#endif

